package com.shopping.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shopping.dto.ProductDTO;
import com.shopping.dto.ProductQueryDTO;
import com.shopping.entity.Product;
import com.shopping.entity.User;
import com.shopping.entity.MemberLevelDiscount;
import com.shopping.mapper.ProductMapper;
import com.shopping.service.ProductService;
import com.shopping.service.UserService;
import com.shopping.service.MemberLevelDiscountService;
import com.shopping.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {

    @Autowired
    private UserService userService;

    @Autowired
    private MemberLevelDiscountService memberLevelDiscountService;

    @Override
    public Page<ProductDTO> getProductList(ProductQueryDTO queryDTO) {
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();

        // 设置查询条件
        if (StringUtils.hasText(queryDTO.getName())) {
            wrapper.and(w -> w
                    .like(Product::getName, queryDTO.getName())
                    .or()
                    .like(Product::getDescription, queryDTO.getName())
            );
        }
        if (StringUtils.hasText(queryDTO.getType())) {
            wrapper.eq(Product::getType, queryDTO.getType());
        }
        if (queryDTO.getMinPrice() != null) {
            wrapper.ge(Product::getPrice, queryDTO.getMinPrice());
        }
        if (queryDTO.getMaxPrice() != null) {
            wrapper.le(Product::getPrice, queryDTO.getMaxPrice());
        }
        if (StringUtils.hasText(queryDTO.getStatus())) {
            wrapper.eq(Product::getStatus, queryDTO.getStatus());
        } else {
            wrapper.eq(Product::getStatus, Product.Status.ON_SALE.name());
        }
        if (queryDTO.getIsRecommended() != null) {
            wrapper.eq(Product::getRecommended, queryDTO.getIsRecommended());
        }

        // 按推荐状态和创建时间倒序排序
        wrapper.orderByDesc(Product::getRecommended)
                .orderByDesc(Product::getCreateTime);

        // 执行分页查询
        Page<Product> page = new Page<>(queryDTO.getPage(), queryDTO.getSize());
        Page<Product> result = this.page(page, wrapper);

        // 转换为DTO
        Page<ProductDTO> dtoPage = new Page<>();
        dtoPage.setRecords(result.getRecords().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList()));
        dtoPage.setTotal(result.getTotal());
        dtoPage.setCurrent(result.getCurrent());
        dtoPage.setSize(result.getSize());

        return dtoPage;
    }

    @Override
    public List<ProductDTO> getRecommendedProducts() {
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Product::getRecommended, true)
                .eq(Product::getStatus, Product.Status.ON_SALE.name())
                .orderByDesc(Product::getRecommended)
                .orderByDesc(Product::getCreateTime)
                .last("LIMIT 8");
        return this.list(wrapper).stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<ProductDTO> getProductsByType(String type) {
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Product::getType, type)
                .eq(Product::getStatus, Product.Status.ON_SALE.name())
                .orderByDesc(Product::getCreateTime);
        return this.list(wrapper).stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<ProductDTO> searchProducts(String keyword) {
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(Product::getName, keyword)
                .or()
                .like(Product::getDescription, keyword)
                .eq(Product::getStatus, Product.Status.ON_SALE.name())
                .orderByDesc(Product::getCreateTime);
        return this.list(wrapper).stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public ProductDTO getProductById(Long id) {
        Product product = this.getById(id);
        return product != null ? convertToDTO(product) : null;
    }

    @Override
    @Transactional
    public ProductDTO createProduct(Product product) {
        // 设置默认值
        if (product.getStatus() == null) {
            product.setStatus(Product.Status.ON_SALE.name());
        }
        if (product.getRecommended() == null) {
            product.setRecommended(false);
        }
        if (product.getProductPoints() == null) {
            product.setProductPoints(0);
        }

        product.setCreateTime(LocalDateTime.now());
        product.setUpdateTime(LocalDateTime.now());
        this.save(product);
        return convertToDTO(product);
    }

    @Override
    @Transactional
    public ProductDTO updateProduct(Long id, Product product) {
        product.setId(id);
        product.setUpdateTime(LocalDateTime.now());
        this.updateById(product);
        return convertToDTO(this.getById(id));
    }

    @Override
    @Transactional
    public void deleteProduct(Long id) {
        this.removeById(id);
    }

    @Override
    @Transactional
    public void toggleProductStatus(Long id) {
        Product product = this.getById(id);
        if (product != null) {
            product.setStatus(product.getStatus().equals(Product.Status.ON_SALE.name())
                    ? Product.Status.OFF_SALE.name()
                    : Product.Status.ON_SALE.name());
            product.setUpdateTime(LocalDateTime.now());
            this.updateById(product);
        }
    }

    @Override
    @Transactional
    public void toggleRecommended(Long id) {
        Product product = this.getById(id);
        if (product != null) {
            product.setRecommended(!product.getRecommended());
            product.setUpdateTime(LocalDateTime.now());
            this.updateById(product);
        }
    }

    @Override
    @Transactional
    public boolean updateStock(Long productId, Integer quantity) {
        Product product = this.getById(productId);
        if (product == null) {
            return false;
        }

        int newStock = product.getStock() - quantity;
        if (newStock < 0) {
            return false;
        }

        product.setStock(newStock);
        product.setUpdateTime(LocalDateTime.now());
        return this.updateById(product);
    }

    @Override
    public Object getProductStatistics() {
        Map<String, Object> statistics = new HashMap<>();

        // 获取商品总数
        long totalProducts = this.count();
        statistics.put("totalProducts", totalProducts);

        // 获取今日新增商品数
        LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        long newProducts = this.count(new LambdaQueryWrapper<Product>()
                .ge(Product::getCreateTime, startOfDay));
        statistics.put("newProducts", newProducts);

        // 获取上架商品数
        long activeProducts = this.count(new LambdaQueryWrapper<Product>()
                .eq(Product::getStatus, Product.Status.ON_SALE.name()));
        statistics.put("activeProducts", activeProducts);

        // 获取推荐商品数
        long recommendedProducts = this.count(new LambdaQueryWrapper<Product>()
                .eq(Product::getRecommended, true));
        statistics.put("recommendedProducts", recommendedProducts);

        // 获取各类型商品数量
        Map<String, Long> typeCounts = new HashMap<>();
        for (Product.ProductType type : Product.ProductType.values()) {
            long count = this.count(new LambdaQueryWrapper<Product>()
                    .eq(Product::getType, type.name()));
            typeCounts.put(type.name(), count);
        }
        statistics.put("typeCounts", typeCounts);

        return statistics;
    }

    @Override
    public List<Map<String, Object>> getProductCategories() {
        try {
            // 直接从products表中获取所有不重复的商品类型
            LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(Product::getType)
                    .groupBy(Product::getType);

            List<Product> products = list(wrapper);

            // 转换为前端需要的格式
            return products.stream()
                    .map(product -> {
                        Map<String, Object> category = new HashMap<>();
                        String type = product.getType();
                        category.put("id", type);
                        category.put("name", Product.ProductType.valueOf(type).getDisplayName());
                        return category;
                    })
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取商品分类失败", e);
            return new ArrayList<>();
        }
    }

    private ProductDTO convertToDTO(Product product) {
        ProductDTO dto = new ProductDTO();
        dto.setId(product.getId());
        dto.setName(product.getName());
        dto.setDescription(product.getDescription());
        dto.setPrice(product.getPrice());
        dto.setStock(product.getStock());
        dto.setType(product.getType());
        dto.setImageUrl(product.getImageUrl());
        dto.setRecommended(product.getRecommended());
        dto.setStatus(product.getStatus());
        dto.setProductPoints(product.getProductPoints());
        dto.setCreateTime(product.getCreateTime());
        dto.setUpdateTime(product.getUpdateTime());

        // 计算会员价、生日价、折扣类型等
        User user = SecurityUtils.getCurrentUser();
        System.out.println("[DEBUG] user=" + user);
        java.math.BigDecimal memberPrice = null;
        java.math.BigDecimal birthdayPrice = null;
        String discountType = "NONE";
        java.math.BigDecimal discountRate = java.math.BigDecimal.ONE;
        java.math.BigDecimal discountAmount = java.math.BigDecimal.ZERO;
        if (user != null) {
            // 会员等级折扣
            MemberLevelDiscount levelDiscount = memberLevelDiscountService.getOne(
                    new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<MemberLevelDiscount>().eq("level", user.getLevel().name())
            );
            if (levelDiscount != null) {
                memberPrice = product.getPrice().multiply(levelDiscount.getDiscountRate()).setScale(2, java.math.RoundingMode.HALF_UP);
            }
            // 生日特权
            boolean isBirthday = false;
            if (user.getBirthday() != null) {
                java.time.LocalDate today = java.time.LocalDate.now();
                isBirthday = today.getMonthValue() == user.getBirthday().getMonthValue() && today.getDayOfMonth() == user.getBirthday().getDayOfMonth();
            }
            if (isBirthday) {
                birthdayPrice = product.getPrice().multiply(new java.math.BigDecimal("0.80")).setScale(2, java.math.RoundingMode.HALF_UP);
                discountType = "BIRTHDAY";
                discountRate = new java.math.BigDecimal("0.80");
                discountAmount = product.getPrice().subtract(birthdayPrice).setScale(2, java.math.RoundingMode.HALF_UP);
            } else if (memberPrice != null && memberPrice.compareTo(product.getPrice()) < 0) {
                discountType = "MEMBER";
                discountRate = levelDiscount.getDiscountRate();
                discountAmount = product.getPrice().subtract(memberPrice).setScale(2, java.math.RoundingMode.HALF_UP);
            }
            System.out.println("[DEBUG] discountType=" + discountType + ", memberPrice=" + memberPrice + ", birthdayPrice=" + birthdayPrice + ", discountRate=" + discountRate + ", discountAmount=" + discountAmount);
        }
        dto.setMemberPrice(memberPrice);
        dto.setBirthdayPrice(birthdayPrice);
        dto.setDiscountType(discountType);
        dto.setDiscountRate(discountRate);
        dto.setDiscountAmount(discountAmount);
        return dto;
    }

    public ProductDTO convertToDTO(Product product, User user) {
        ProductDTO dto = new ProductDTO();
        dto.setId(product.getId());
        dto.setName(product.getName());
        dto.setDescription(product.getDescription());
        dto.setPrice(product.getPrice());
        dto.setStock(product.getStock());
        dto.setType(product.getType());
        dto.setImageUrl(product.getImageUrl());
        dto.setRecommended(product.getRecommended());
        dto.setStatus(product.getStatus());
        dto.setProductPoints(product.getProductPoints());
        dto.setCreateTime(product.getCreateTime());
        dto.setUpdateTime(product.getUpdateTime());

        // 计算会员价、生日价、折扣类型等
        java.math.BigDecimal memberPrice = null;
        java.math.BigDecimal birthdayPrice = null;
        String discountType = "NONE";
        java.math.BigDecimal discountRate = java.math.BigDecimal.ONE;
        java.math.BigDecimal discountAmount = java.math.BigDecimal.ZERO;
        if (user != null) {
            // 会员等级折扣
            MemberLevelDiscount levelDiscount = memberLevelDiscountService.getOne(
                    new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<MemberLevelDiscount>().eq("level", user.getLevel().name())
            );
            if (levelDiscount != null) {
                memberPrice = product.getPrice().multiply(levelDiscount.getDiscountRate()).setScale(2, java.math.RoundingMode.HALF_UP);
            }
            // 生日特权
            boolean isBirthday = false;
            if (user.getBirthday() != null) {
                java.time.LocalDate today = java.time.LocalDate.now();
                isBirthday = today.getMonthValue() == user.getBirthday().getMonthValue() && today.getDayOfMonth() == user.getBirthday().getDayOfMonth();
            }
            if (isBirthday) {
                birthdayPrice = product.getPrice().multiply(new java.math.BigDecimal("0.80")).setScale(2, java.math.RoundingMode.HALF_UP);
                discountType = "BIRTHDAY";
                discountRate = new java.math.BigDecimal("0.80");
                discountAmount = product.getPrice().subtract(birthdayPrice).setScale(2, java.math.RoundingMode.HALF_UP);
            } else if (memberPrice != null && memberPrice.compareTo(product.getPrice()) < 0) {
                discountType = "MEMBER";
                discountRate = levelDiscount.getDiscountRate();
                discountAmount = product.getPrice().subtract(memberPrice).setScale(2, java.math.RoundingMode.HALF_UP);
            }
        }
        dto.setMemberPrice(memberPrice);
        dto.setBirthdayPrice(birthdayPrice);
        dto.setDiscountType(discountType);
        dto.setDiscountRate(discountRate);
        dto.setDiscountAmount(discountAmount);
        return dto;
    }
}